<?php
/**
 * $Id$
 *  @package	Joomla
 *  @author Daniel Eliasson
* 	@copyright	Copyright (C) 2011 Stilero. All rights reserved.
* 	@license	GPLv2
 * 
	This file is part of BlogPing.

    BlogPing is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Foobar is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with BlogPing.  If not, see <http://www.gnu.org/licenses/>.
*/

// no direct access
defined('_JEXEC') or die('Restricted access'); 

// Import library dependencies
jimport('joomla.plugin.plugin');

/**
 * 
 * @author Daniel Eliasson 
 * @package Joomla
 *
 */

class plgContentBlogping extends JPlugin
{
    var $donationURL = 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NE4YM64RE6PMS';
    var $blogPingProURL = 'http://www.stilero.com/downloads/joomla-plugins/blogping-pro.html';
    var $ratingURL = 'http://extensions.joomla.org/extensions/authoring-a-content/blog/7702';
	
    public function plgContentBlogping( &$subject, $config )
    {
		parent::__construct( $subject, $config );
		$this->loadLanguage();
		
		//This is used to check if we're in the frontend or backend
		$frontend;
		
    }
	
    /**
     * This is the main method for the plugin. It creates necessary links and makes all calls to the pingfunctions.
     * 
     * @param	string	$context	The context of the content being passed to the plugin.
	 * @param	object	&$article	The article object.  Note $article->text is also available
	 * @param	boolean	$isNew		Boolean showing if the article is new
	 * 
	 * @return	void
	 * 
	 * @since	1.6
     */
	public function onContentAfterSave($context, &$article, $isNew)
    {
    	global $mainframe, $mosConfig_sitename,$mosConfig_live_site;
    	//Get the absolute path to the site
    	$mosConfig_absolute_path = JPATH_SITE;
            //Check if we are ready to ping, and then begin pinging.
            $pingUpdates = ($this->params->def('pingnew'))?FALSE:TRUE;
            if($this->_checkBeforePing($article, $pingUpdates)){
                    $this->_startPings($article);
            }
            $this->_ratingReminder();
            $this->_supportReminder();
            return true;
	}
	/**
     * This is the main method for the plugin. It creates necessary links and makes all calls to the pingfunctions.
     * 
	 * @param	object	&$article	The article object.  Note $article->text is also available
	 * @param	boolean	$isNew		Boolean showing if the article is new
	 * 
	 * @return	void
	 * 
	 * @since	1.5
     */
	public function onAfterContentSave( &$article, $isNew )
	{
		//Check if we are ready to ping, and then begin pinging.
		$pingUpdates = ($this->params->def('pingnew'))?FALSE:TRUE;
		if($this->_checkBeforePing($article, $pingUpdates)){
			$this->_startPings($article);
		}
                $this->_ratingReminder();
                $this->_supportReminder();
                return true;
	}
	
	
	/**
	 * Method makes some initial checks to see if this is an article to ping for.
	 * @param	object	&$article		The article object.  Note $article->text is also available
	 * @param 	boolean	$pingOnUpdates	(Optional) True skips db check if article already pinged.	
	 *
	 * @return	boolean
	 * @since	1.6
	 */
	function _checkBeforePing($article, $pingOnUpdates=FALSE)
	{
		//Variables used for changes since 1.5
		$sectionCat;	//Used for sections (1.5) or categories (1.6+)
		$publicAccess;
		
		
		if(version_compare(JVERSION,'1.7.0','ge')) {
			$sectionCat = $article->catid;
			$publicAccess = 1;
		} elseif(version_compare(JVERSION,'1.6.0','ge')) {
			$sectionCat = $article->catid;
			$publicAccess = 1;
		} elseif(version_compare(JVERSION,'1.5.0','ge')) {
			$sectionCat = $article->sectionid;
			$publicAccess = 0;
		}

		// Get plugin parameters set by the user
		$pinglist = $this->params->def('pinglist');
		$pingsection = $this->params->def('section_id');
		$pingsectionarray = explode(",", $this->params->def('section_id'));
		$pingnew = $this->params->def('pingnew');
		
		//First check the following:
		// * Do we have a serverlist ready?
		// * is this a section to ping?
		// * is this article active?
		// * is this article published?
		// * is this article public ?
		// If not, return and end this ping session.
		
		//Check if pingserver is specified
		if( $pinglist == "" ){
			$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_NOPINGSERVER'));
			return FALSE;
		}
		
		
		//Article active?
		if (($article->state!=1)){
			$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_NOTACTIVE'));
			return FALSE;
		}
		
		//Article published?
		$currentDate = $date =& JFactory::getDate();
		//If the article should be published in the future, then we wont ping
		if ( $article->publish_up > $date->toMySQL() ){
			$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_NOTPUBLISHED'));
			return FALSE;
		}
		
		
		
		//Is the article only for registred users?
		if( $article->access != $publicAccess ){
			$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_RESTRICT'));
			return FALSE;
		}
		
		
		//Section to ping?
		if ( $pingsection != "" ){
			//The sectionlist is not empty, so we must check which categories to ping
						
			if ( !in_array($sectionCat, $pingsectionarray) ){
				$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_NOTSECTION'));
				return FALSE;
			}
		}
		
		// Next check if this article is new, and if ping should be made only on new articles
		if ( ( $pingnew == 1 ) && ( $article->version != 1 ) ){
			//JFactory::getApplication()->enqueueMessage(JText::_('NOTNEW'));
			$this->_displayMessage(JText::_('PLG_CONTENT_BLOGPING_NOTNEW'));
			return FALSE;
		}
		

		
		return TRUE;
	}
        
        private function _supportReminder(){
            $donationStringStart = '<a href="'.$this->donationURL.'" target="_blank">';
            $stringsEnd = '</a>';
            $upgradeStringStart = '<a href="'.$this->blogPingProURL.'" target="_blank">';
            JERROR::raiseNotice(100, JText::sprintf( 'PLG_CONTENT_BLOGPING_SUPPORT', $donationStringStart, $stringsEnd, $upgradeStringStart, $stringsEnd ));
        }
        
        private function _ratingReminder(){
            $now = time();
            $nextReminder = $this->params->def('appirater');
            if($nextReminder > $now || $nextReminder == "0000000000"){
                return;
            }
            $ratingStringStart = '<a href="'.$this->ratingURL.'" target="_blank">';
            $stringsEnd = '</a>';
            JERROR::raiseNotice(101, JText::sprintf( 'PLG_CONTENT_BLOGPING_RATE', $ratingStringStart, $stringsEnd ));
        }
        
	/**
	 * This method handles the pinging
	 * 
	 * @access private
	 * @author Daniel
	 * 
	 * @param object	&$article	content object.
	 * 
	 * @return void
	 */
	function _startPings($article){
		
		//Create an array with all pingservers specified by the user.
		//First check if more than one server is specified
		
		$pinglist=  $this->params->def('pinglist');
		$pingservers;
		$fullurl = $this->_getRootURL();
		if(substr_count($pinglist, "\n")>0){
			$pingservers=explode("\n", $pinglist);
		}else{
			$pingservers[0]=$pinglist;
		}
		
		$urlMode = 'standard';
		

		$host = $_SERVER['HTTP_HOST'];
		
		//Create a full url to the article, and a message containing the title of the article.
		
		$message="url: ".JText::_($article->title)."\n";
		//Get the Site name
		$app    = JApplication::getInstance('site');
		$websiteName = JText::_($app->getCfg('sitename'));
		
		//Put together an array of the site name and the root url.
		//$blogpost = array("title" => htmlentities(JText::_($article->title)), "postlink" => htmlentities($fullurl));
		$blogpost = array("title" => $websiteName, "postlink" => htmlentities($fullurl));
		
		//Check if pingserver is set, or show an error message
		if(count($pingservers)>0){
			
			//Go throug all the pingservers an start pinging.
			foreach ( $pingservers as $server )
			{
				$response=$this->_pingServer($server, $blogpost);
				$msg="PingService: ".$server." - <".$response[0]."> - ".$response[1];
				
				switch($response[0]){
					case 0: 
						$this->_displayMessage( $msg);
						break;
					case 1: 
						$this->_displayMessage( $msg, 'error');
						break;
					default:
						$this->_displayMessage( $msg);
						break;
				}
	
	
			}
		}else{
			$this->_displayMessage( JText::_('PLG_CONTENT_BLOGPING_NOPINGSERVER'), 'error');
		}
	}
	
	
	
	/**
	 * This method returns a Joomla url based on article and id.
	 * Note: This method should no longer be used by the blogping, since the root url is used instead.
	 * 
	 * @access private
	 * @author Daniel
	 * 
	 * @param object	&$article	content object.
	 * 
	 * @return string	article url
	 * 
	 * @since 1.6
	 */
	function _createUrl($article)
	{
		//Variables used for changes since 1.5
		$sectionCat;	//Used for sections (1.5) or categories (1.6+)
		
		if(version_compare(JVERSION,'1.7.0','ge')) {
			$sectionCat = $article->catid;
		} elseif(version_compare(JVERSION,'1.6.0','ge')) {
			$sectionCat = $article->catid;
		} else {
			$sectionCat = $article->sectionid;
		}
		
			if(!class_exists('ContentHelperRoute')) require_once (JPATH_SITE . '/components/com_content/helpers/route.php'); 
				
			
				$app    = JApplication::getInstance('site');
				$theRouter = &$app->getRouter();
				
	
				//Create slug like  1:my-alias.html if SEF turned on, otherwise return article id
				$slug = ($app->getCfg('sef'))?$article->id.":".$article->alias:$article->id;
				
				//Get SEF URL based on slug and category id
				$articleLink = ContentHelperRoute::getArticleRoute($slug, $sectionCat);
				
				$link = $theRouter->build($articleLink);
				
				//Remove administrator trash. TODO: make this remove itself
				$link = str_replace("/administrator", "", $link->toString());
				
				//Remove the irritating trailing slash that root produces
				$link = str_replace("/component/content/article", "", $link) ;
				
				
				//Make host url without the ending slash
				$hosturl = substr(JURI::root(), 0, strlen(JURI::root())-1 );
				//Make sure the host is not in the current link, since well add it later.
				//This is required for some SEF-plugins that add the host.
				$link = str_replace($hosturl, "", $link);
				//Add the hosturl again
				$link = $hosturl.$link;
				
				//Decode the url to work universally
				$link = htmlentities($link);
				
				
		return $link;
	}
	/**
	 * This method returns the Root URL
	 * I've decided to keep this in a separate method in case of future Joomla changes.
	 * 
	 * @access private
	 * @author Daniel
	 * 
	 * 
	 * @return string	root url
	 * 
	 */
	function _getRootURL()
	{
		//Variables used for changes since 1.5
		$link;
		
		if(version_compare(JVERSION,'1.7.0','ge')) {
			$link = JURI::root();
		} elseif(version_compare(JVERSION,'1.6.0','ge')) {
			$link = JURI::root();
		} else {
			$link = JURI::root();
		}
				
		return $link;
	}

	
	/**
	 * This method makes a connection to the ping server and returns any errorcode occured.
	 * 
	 * @access private
	 * 
	 * @param string	$URL		url of the pingservice to use
	 * @param array		$blogpost	array with the article 'title' and article url 'blogpost'
	 * 
	 * @return  array 	array with error type and errormessage
	 */
	function _pingServer($URL, $blogpost)
	{
		$parse = parse_url($URL);
		if(!isset($parse['host'])) return false;
		$host = $parse['host'];
		$scheme = $parse['scheme']."://";
		$port = isset($parse['port'])?$parse['port']:80;
		$uri  = isset($parse['path'])?$parse['path']:'/';
		
		if($debuggingBlogPing){
			$this->_displayMessage( "Trying to ping: ".$host.$uri);
		}
		
		$fp=fsockopen($host, $port,$errno,$errstr);
		//$fp=fsockopen($URL,$port,$errno,$errstr);
		if(!$fp){		
			return array(-1,"Cannot open connection: $errstr ($errno)<br />\r\n");	
		}
						
		//Set methodname according to ping type
		$methodName = "weblogUpdates.ping";			

		$data = "<?xml version=\"1.0\"?>\r\n
		<methodCall>\r\n
  			<methodName>".$methodName."</methodName>\r\n
	  		<params>\r\n
	    		<param>\r\n
	      			<value><string>".$blogpost['title']."</string></value>\r\n
	    		</param>\r\n
	    		<param>\r\n
	      			<value><string>".$blogpost['postlink']."</string></value>\r\n
	    		</param>\r\n
	  		</params>\r\n
		</methodCall>";
		
		
		$len  = strlen($data);
		$out  = "POST $uri HTTP/1.0\r\n";
		$out .= "User-Agent: BlogPing 1.0\r\n";
		$out .= "Host: $host\r\n";
		$out .= "Content-Type: text/xml\r\n";
		$out .= "Content-length: $len\r\n\r\n";
		$out .= $data;
	
		fwrite($fp, $out);
		$response = '';
		while(!feof($fp)) $response.=fgets($fp, 128);
		fclose($fp);

		$lines=explode("\r\n",$response);
		$firstline=$lines[0];
		if(!ereg("HTTP/1.[01] 200 OK",$firstline))
		{	
			return array(-1,$firstline);	
		}

		while($lines[0]!='') array_shift($lines);
		array_shift($lines);
		$lines=strip_tags(implode(' ',$lines));

		$n=preg_match(
		'|<member>\s*<name>flerror</name>\s*<value>\s*<boolean>([^<]*)</boolean>\s*</value>\s*</member>|i',
		$response, $matches);
		if(0==$n)
		{	return array(-1,$lines);	}
		$flerror=$matches[1];

		$n=preg_match(
		'|<member>\s*<name>message</name>\s*<value>\s*<string>([^<]*)</string>\s*</value>\s*</member>|i',
		$response, $matches);
		if(0==$n)
		{	return array(-1,$lines);	}
		$message=$matches[1];
		

		
		return array($flerror,$message);
	}
	/**
	 * This method takes care of messagees to display.
	 * 
	 * @access private
	 * 
	 * @param string	$message		the message to display
	 * @param array		$messageType	type of message to display. "error" for errormessages, otherwise blank.
	 * 
	 * @return  void
	 */
	function _displayMessage($msg, $messageType = "")
	{
		
		//Check if messages is turned on, otherwise return
		if($this->params->def('pingmessages')==0){
		
			return;
		}
		
		JFactory::getApplication()->enqueueMessage( $msg, $messageType);
		
	}
} 

?>